package EA.testLSs;
import EA.*;
import EA.testproblems.*;
import EA.operators.selection.*;
import EA.operators.localsearch.*;
import EA.recording.*;
import java.util.Hashtable;
import RKUjava.datastructures.RKUVector;
import RKUjava.util.*;
import RKUjava.lang.RKUCloneable;
import Visualization.plot.*;

/** Implements a steepest ascend local search.
    It is possible to run the SALS with either bit 
    representation, realvector representation, or realvector with stepsizes.
    The following is a simple implementation of the main class.<br>
    <pre>
    import EA.*;
    import EA.testproblems.*;
    import EA.testLSs.SteepestAscend;
    
    public class sals
    {
      &nbsp;&nbsp;static NumericalProblem curproblem;
      &nbsp;&nbsp;static SteepestAscend sa;
      &nbsp;&nbsp;static BatchJobScheduler BJS;
    
      &nbsp;&nbsp;public static void main(String argv[])
        &nbsp;&nbsp;{
	  &nbsp;&nbsp;&nbsp;&nbsp;if (argv.length==0){
	    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println((new SteepestAscend()).getDefaultSettings());
	    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.exit(0);
	  &nbsp;&nbsp;&nbsp;&nbsp;}
	  &nbsp;&nbsp;&nbsp;&nbsp;curproblem = new UrsemMultimodal1();
  	  &nbsp;&nbsp;&nbsp;&nbsp;sa = new SteepestAscend(curproblem);
	  &nbsp;&nbsp;&nbsp;&nbsp;BJS = new BatchJobScheduler(sa);
	  &nbsp;&nbsp;&nbsp;&nbsp;BJS.startScheduler(argv);
	  &nbsp;&nbsp;&nbsp;&nbsp;System.exit(0);
        &nbsp;&nbsp;}
    }</pre>

    @see EA.BitNumericalGenome
    @see EA.RealNumericalGenome
    @see EA.DiscreteRNumGenome
*/
public class SteepestAscend implements BatchJobEA
{

  /** Representation type. (Default = 0)<br>
      0 = Realvalue vectors with RealNumericalGenome.<br>
      1 = Bitrepresented vectors with BitNumericalGenome.<br>
      2 = Realvalue vectors with DiscreteRNumGenome.<br>
  */
  public int representationtype = 0;
    
  /** The current problem. */
  public NumericalProblem curproblem;

  /** The current framework. */
  public NumericalFramework nf;
    
  /** Create a steepest ascend local search.<br><b>Note:</b> Remember to set curproblem. */
  public SteepestAscend()
    {
      super();
    }

  /** Create a steepest ascend local search with the given problem. */
  public SteepestAscend(NumericalProblem aproblem)
    {
      super();
      curproblem = aproblem;
    }

  // **** BatchJob implementation *****************************

  /** Set the settings for the algorithm. The passed hashtable contains
      only String objects which are all related to the input file given 
      to the scheduler. 
  */
  public void setSettings(Hashtable settings)
    {
      String curstr;

      if ((curstr = (String)settings.get("representationtype"))!=null) {
	representationtype = (new Integer(curstr)).intValue();
      }

      switch (representationtype) {
      case 0:
	nf = new RealSteepestAscendFramework(curproblem);
	((RealSteepestAscendFramework)nf).theGA = this;
	break;
      case 1:
	nf = new BitSteepestAscendFramework(curproblem);
	((BitSteepestAscendFramework)nf).theGA = this;
	break;
      case 2:
	nf = new DiscSteepestAscendFramework(curproblem);
	((DiscSteepestAscendFramework)nf).theGA = this;
	break;
      }
      ((BatchJobEA)nf).setSettings(settings);

    };

  /** Get the default settings in the BatchJobScheduler format. This 
      method can be used to reconstruct an input file for the scheduler. 
  */
  public String getDefaultSettings()
    {
      RealSteepestAscendFramework f = new RealSteepestAscendFramework();
      StringBuffer res = new StringBuffer();

      res.append(BatchJobScheduler.getDefaultSettings());
      res.append("#################################################################\n");
      res.append("# ------------- Algorithmic settings ----------------------------\n");
      res.append("\n");
      res.append("# Problem name\n");
      res.append("problemname = UrsemMultimodal1\n");
      res.append("\n");
      res.append("# Print information to stdout (true/false)\n");
      res.append("verbose = "+f.verbose+"\n");
      res.append("\n");
      res.append("# Save results from all repetitions\n");
      res.append("saveallrepetitions = true\n");
      res.append("\n");
      res.append("# Save best results from all repetitions\n");
      res.append("savebestrepetition = true\n");
      res.append("\n");
      res.append("# Representation type\n");
      res.append("#  0 = Real valued vectors (RealNumericalGenome).\n");
      res.append("#  1 = Binary encoded vectors (BitNumericalGenome).\n");
      res.append("#  2 = Real valued vectors with steps (DiscreteRNumGenome).\n");
      res.append("representationtype = "+representationtype+"\n");
      res.append("\n");
      res.append("# Range of localsearch if representationtype = 0\n");
      res.append("realrange = 0.01\n");
      res.append("\n");
      res.append("# Number of bits per variable if representationtype = 1\n");
      res.append("bitspervariable = 20\n");
      res.append("\n");
      res.append("# Stepsizes if representationtype = 2 (PROBLEM DEPENDENT)\n");
      res.append("stepsizes = ()\n");
      res.append("\n");
      res.append("# Maximal number of iterations\n");
      res.append("# 0 = optimize until stagnation\n");
      res.append("maxiterations = 0\n");
      res.append("\n");
      res.append("# Number of repetitions\n");
      res.append("repetitions = 100\n");
      res.append("\n");

      return res.toString();
    };

  /** Initialize a batchjob. This is called once before any run is performed.
   */
  public void initializeBatchJobs()
    {};

  /** Finalize a batchjob. This is called once after all runs are performed.
   */
  public void finalizeBatchJobs()
    {
      ((BatchJobEA)nf).finalizeBatchJobs();
    };


  /** Initialize a run series. This is called once before the specified 
      number of runs are performed. (BJSruns in the batchfile)
  */
  public void initializeRunSeries()
    {
      ((BatchJobEA)nf).initializeRunSeries();
    };

  /** Finalize a run series. This is called once after the specified 
      number of runs are performed. (BJSruns in the batchfile)
  */
  public void finalizeRunSeries()
    {
      ((BatchJobEA)nf).finalizeRunSeries();
    };

  /** Initialize and start a single run of the algorithm. You can 
      usually just call doEA() from your framework.
  */
  public void initializeAndStartRun()
    {
      ((BatchJobEA)nf).initializeAndStartRun();
    };

  /** Finalize the single run of the algorithm. This is called immediately
      after the initializeAndStartRun(). It can be used to reset 
      measurements, increase counters, etc.
  */
  public void finalizeRun()
    {
      ((BatchJobEA)nf).finalizeRun();
    };

  /** Get the run data as text. Your implementation must return
      an array of objects that each implements the interface ConvertToText from the package
      EA.recording. You can use the classes found in EA.recording or 
      implement your own classes.
      @see EA.recording.ConvertToText
  */
  public Object[] getDataAsText()
    {
      return ((BatchJobEA)nf).getDataAsText();
    };
}

class RealSteepestAscendFramework extends RealNumericalFramework implements BatchJobEA
{

  // True if the info should be printed to stdout
  boolean verbose;

  boolean saveallrepetitions = false;

  boolean savebestrepetition = false;

  // Maximal number of iterations
  public int maxiterations = 0;

  // Range of reals in local search
  public double realrange;

  // Initial number of individuals
  public int repetitions = 100;

  // Is this problem a maximization problem.
  public boolean ismaximization = true;

  public boolean isdynamicproblem = false;

  public NumericalProblem curproblem;

  public SteepestAscendIndividual[] population;

  public SteepestAscend theGA;


  private SequenceTable results1, results2;

  /** Create a new framework. */
  public RealSteepestAscendFramework()
    {
      super();
    }

  /** Create a new framework. */
  public RealSteepestAscendFramework(NumericalProblem numproblem)
    {
      super(numproblem);

      curproblem = numproblem;
      ismaximization = curproblem.ismaximization;
    }

  public boolean terminate()
    {
      return false;
    }

  public void Framework_initialize_inner()
    {
      int i;
      population = new SteepestAscendIndividual[repetitions];

      for (i = 0;i<repetitions;i++) {
	population[i] = new SteepestAscendIndividual(this, true, theGA.representationtype);
	population[i].localSearch();

	if (verbose)
	  System.out.println(i+": Bestfit="+population[i].getFitness()+"  "+RKUStringUtils.arrayToString(population[i].getPos(),5));

      };

    };

  // **** BatchJob implementation *****************************

  /** Set the settings for the algorithm. The passed hashtable contains
      only String objects which are all related to the input file given 
      to the scheduler. 
  */
  public void setSettings(Hashtable settings)
    {
      String curstr;

      if ((curstr = (String)settings.get("verbose"))!=null) {
	verbose = (new Boolean(curstr)).booleanValue();
      }

      if ((curstr = (String)settings.get("saveallrepetitions"))!=null) {
	saveallrepetitions = (new Boolean(curstr)).booleanValue();
      }

      if ((curstr = (String)settings.get("savebestrepetition"))!=null) {
	savebestrepetition = (new Boolean(curstr)).booleanValue();
      }

      if ((curstr = (String)settings.get("maxiterations"))!=null) {
	maxiterations = (new Integer(curstr)).intValue();
      }

      if ((curstr = (String)settings.get("repetitions"))!=null) {
	repetitions = (new Integer(curstr)).intValue();
      }

      if( (curstr = (String)settings.get("realrange"))!=null) {
	realrange = (new Double(curstr)).doubleValue();
      }

      if ((curstr = (String)settings.get("problemname"))!=null) {
	  curproblem = NumericalProblemSelector.selectProblem(curstr);
	  setProblem(curproblem);
	  ismaximization = curproblem.ismaximization;
      }

      curproblem.setSettings(settings, this);

    };

  /** Get the default settings in the BatchJobScheduler format. This 
      method can be used to reconstruct an input file for the scheduler. 
  */
  public String getDefaultSettings()
    {
      return "";
    };

  /** Initialize a batchjob. This is called once before any run is performed.
   */
  public void initializeBatchJobs()
    {
    };

  /** Finalize a batchjob. This is called once after all runs are performed.
   */
  public void finalizeBatchJobs()
    {
    };

  /** Initialize a run series. This is called once before the specified 
      number of runs are performed. (BJSruns in the batchfile)
  */
  public void initializeRunSeries()
    {};

  /** Finalize a run series. This is called once after the specified 
      number of runs are performed. (BJSruns in the batchfile)
  */
  public void finalizeRunSeries()
    {};

  /** Initialize and start a single run of the algorithm. You can 
      usually just call doEA() from your framework.
  */
  public void initializeAndStartRun()
    {
      doEA();
    };

  /** Finalize the single run of the algorithm. This is called immediately
      after the initializeAndStartRun(). It can be used to reset 
      measurements, increase counters, etc.
  */
  public void finalizeRun()
    {
    };

  /** Get the run data as text. Your implementation must return
      an array of objects that each implements the interface ConvertToText from the package
      EA.recording. You can use the classes found in EA.recording or 
      implement your own classes.
      @see EA.recording.ResultSet
      @see EA.recording.Measurement
      @see EA.recording.ConvertToText
  */
  public Object[] getDataAsText()
    {
      int i;
      RKUVector resvec = new RKUVector();
      SteepestAscendIndividual best;

      if (saveallrepetitions) {
	results1 = new SequenceTable("all_repetitions");
	results1.addColumn(new SequenceTableColumn("Bestfit"));
	results1.addColumns(curproblem.getSequenceTableColumns(""));

	for (i=0; i<population.length;i++) {
	  results1.initializeRow();
	  results1.updateLastRow(0,population[i].getFitness());
	  results1.updateLastRow(1,population[i].getPos());
	}

	resvec.addElement(results1);
      }

      if (savebestrepetition) {
	results2 = new SequenceTable("best_repetition");
	results2.addColumn(new SequenceTableColumn("Bestfit"));
	results2.addColumns(curproblem.getSequenceTableColumns(""));

	best = population[PopulationMeasurements.indexOfBest(population, ismaximization)];
	results2.initializeRow();
	results2.updateLastRow(0,best.getFitness());
	results2.updateLastRow(1,best.getPos());

	resvec.addElement(results2);
      }

      return resvec.toArray();
    };

}

class BitSteepestAscendFramework extends BitNumericalFramework implements BatchJobEA
{

  // True if the info should be printed to stdout
  boolean verbose;

  boolean saveallrepetitions = false;

  boolean savebestrepetition = false;

  // Maximal number of iterations
  public int maxiterations = 0;

  // Initial number of individuals
  public int repetitions = 100;

  // Is this problem a maximization problem.
  public boolean ismaximization = true;

  public boolean isdynamicproblem = false;

  public NumericalProblem curproblem;

  public SteepestAscendIndividual[] population;

  public SteepestAscend theGA;

  int bitspervariable = 20;

  private SequenceTable results1, results2;

  /** Create a new framework. */
  public BitSteepestAscendFramework()
    {
      super();
    }

  /** Create a new framework. */
  public BitSteepestAscendFramework(NumericalProblem numproblem)
    {
      super(numproblem);

      curproblem = numproblem;
      ismaximization = curproblem.ismaximization;
    }

  public boolean terminate()
    {
      return false;
    }

  public void Framework_initialize_inner()
    {
      int i;
      population = new SteepestAscendIndividual[repetitions];

      for (i = 0;i<repetitions;i++) {
	population[i] = new SteepestAscendIndividual(this, true, theGA.representationtype);
	population[i].localSearch();

	if (verbose)
	  System.out.println(i+": Bestfit="+population[i].getFitness()+"  "+RKUStringUtils.arrayToString(population[i].getPos(),5));

      };

    };

  // **** BatchJob implementation *****************************

  /** Set the settings for the algorithm. The passed hashtable contains
      only String objects which are all related to the input file given 
      to the scheduler. 
  */
  public void setSettings(Hashtable settings)
    {
      String curstr;

      if ((curstr = (String)settings.get("verbose"))!=null) {
	verbose = (new Boolean(curstr)).booleanValue();
      }

      if ((curstr = (String)settings.get("saveallrepetitions"))!=null) {
	saveallrepetitions = (new Boolean(curstr)).booleanValue();
      }

      if ((curstr = (String)settings.get("savebestrepetition"))!=null) {
	savebestrepetition = (new Boolean(curstr)).booleanValue();
      }

      if ((curstr = (String)settings.get("maxiterations"))!=null) {
	maxiterations = (new Integer(curstr)).intValue();
      }

      if ((curstr = (String)settings.get("repetitions"))!=null) {
	repetitions = (new Integer(curstr)).intValue();
      }

      if ((curstr = (String)settings.get("bitspervariable"))!=null) {
	bitspervariable = (new Integer(curstr)).intValue();
	setBitsPerVariable(bitspervariable);
      }


      if ((curstr = (String)settings.get("problemname"))!=null) {
	  curproblem = NumericalProblemSelector.selectProblem(curstr);
	  setProblem(curproblem);
	  ismaximization = curproblem.ismaximization;
      }

      curproblem.setSettings(settings, this);

    };

  /** Get the default settings in the BatchJobScheduler format. This 
      method can be used to reconstruct an input file for the scheduler. 
  */
  public String getDefaultSettings()
    {
      return "";
    };

  /** Initialize a batchjob. This is called once before any run is performed.
   */
  public void initializeBatchJobs()
    {
    };

  /** Finalize a batchjob. This is called once after all runs are performed.
   */
  public void finalizeBatchJobs()
    {
    };

  /** Initialize a run series. This is called once before the specified 
      number of runs are performed. (BJSruns in the batchfile)
  */
  public void initializeRunSeries()
    {};

  /** Finalize a run series. This is called once after the specified 
      number of runs are performed. (BJSruns in the batchfile)
  */
  public void finalizeRunSeries()
    {};

  /** Initialize and start a single run of the algorithm. You can 
      usually just call doEA() from your framework.
  */
  public void initializeAndStartRun()
    {
      doEA();
    };

  /** Finalize the single run of the algorithm. This is called immediately
      after the initializeAndStartRun(). It can be used to reset 
      measurements, increase counters, etc.
  */
  public void finalizeRun()
    {
    };

  /** Get the run data as text. Your implementation must return
      an array of objects that each implements the interface ConvertToText from the package
      EA.recording. You can use the classes found in EA.recording or 
      implement your own classes.
      @see EA.recording.ResultSet
      @see EA.recording.Measurement
      @see EA.recording.ConvertToText
  */
  public Object[] getDataAsText()
    {
      int i;
      RKUVector resvec = new RKUVector();
      SteepestAscendIndividual best;

      if (saveallrepetitions) {
	results1 = new SequenceTable("all_repetitions");
	results1.addColumn(new SequenceTableColumn("Bestfit"));
	results1.addColumns(curproblem.getSequenceTableColumns(""));

	for (i=0; i<population.length;i++) {
	  results1.initializeRow();
	  results1.updateLastRow(0,population[i].getFitness());
	  results1.updateLastRow(1,population[i].getPos());
	}

	resvec.addElement(results1);
      }

      if (savebestrepetition) {
	results2 = new SequenceTable("best_repetition");
	results2.addColumn(new SequenceTableColumn("Bestfit"));
	results2.addColumns(curproblem.getSequenceTableColumns(""));

	best = population[PopulationMeasurements.indexOfBest(population, ismaximization)];
	results2.initializeRow();
	results2.updateLastRow(0,best.getFitness());
	results2.updateLastRow(1,best.getPos());

	resvec.addElement(results2);
      }

      return resvec.toArray();
    };

}

class DiscSteepestAscendFramework extends DiscreteRNumFramework implements BatchJobEA
{

  // True if the info should be printed to stdout
  boolean verbose;

  boolean saveallrepetitions = false;

  boolean savebestrepetition = false;

  // Maximal number of iterations
  public int maxiterations = 0;

  // Range of reals in local search
  public double realrange;

  // Initial number of individuals
  public int repetitions = 100;

  // Is this problem a maximization problem.
  public boolean ismaximization = true;

  public boolean isdynamicproblem = false;

  public NumericalProblem curproblem;

  public SteepestAscendIndividual[] population;

  public SteepestAscend theGA;

  double[] stepsizes;

  private SequenceTable results1, results2;

  /** Create a new framework. */
  public DiscSteepestAscendFramework()
    {
      super();
    }

  /** Create a new framework. */
  public DiscSteepestAscendFramework(NumericalProblem numproblem)
    {
      super(numproblem);

      curproblem = numproblem;
      ismaximization = curproblem.ismaximization;
    }

  public boolean terminate()
    {
      return false;
    }

  public void Framework_initialize_inner()
    {
      int i;
      population = new SteepestAscendIndividual[repetitions];

      for (i = 0;i<repetitions;i++) {
	population[i] = new SteepestAscendIndividual(this, true, theGA.representationtype);
	population[i].localSearch();

	if (verbose)
	  System.out.println(i+": Bestfit="+population[i].getFitness()+"  "+RKUStringUtils.arrayToString(population[i].getPos(),5));

      };

    };

  // **** BatchJob implementation *****************************

  /** Set the settings for the algorithm. The passed hashtable contains
      only String objects which are all related to the input file given 
      to the scheduler. 
  */
  public void setSettings(Hashtable settings)
    {
      String curstr;

      if ((curstr = (String)settings.get("verbose"))!=null) {
	verbose = (new Boolean(curstr)).booleanValue();
      }

      if ((curstr = (String)settings.get("saveallrepetitions"))!=null) {
	saveallrepetitions = (new Boolean(curstr)).booleanValue();
      }

      if ((curstr = (String)settings.get("savebestrepetition"))!=null) {
	savebestrepetition = (new Boolean(curstr)).booleanValue();
      }

      if ((curstr = (String)settings.get("maxiterations"))!=null) {
	maxiterations = (new Integer(curstr)).intValue();
      }

      if ((curstr = (String)settings.get("repetitions"))!=null) {
	repetitions = (new Integer(curstr)).intValue();
      }

      if( (curstr = (String)settings.get("realrange"))!=null) {
	realrange = (new Double(curstr)).doubleValue();
      }

      if ((curstr = (String)settings.get("stepsizes"))!=null) {
	stepsizes = RKUStringUtils.stringToDoubleArray(curstr);
	setDiscreteStepsize(stepsizes);
      }


      if ((curstr = (String)settings.get("problemname"))!=null) {
	  curproblem = NumericalProblemSelector.selectProblem(curstr);
	  setProblem(curproblem);
	  ismaximization = curproblem.ismaximization;
      }

      curproblem.setSettings(settings, this);

    };

  /** Get the default settings in the BatchJobScheduler format. This 
      method can be used to reconstruct an input file for the scheduler. 
  */
  public String getDefaultSettings()
    {
      return "";
    };

  /** Initialize a batchjob. This is called once before any run is performed.
   */
  public void initializeBatchJobs()
    {
    };

  /** Finalize a batchjob. This is called once after all runs are performed.
   */
  public void finalizeBatchJobs()
    {
    };

  /** Initialize a run series. This is called once before the specified 
      number of runs are performed. (BJSruns in the batchfile)
  */
  public void initializeRunSeries()
    {};

  /** Finalize a run series. This is called once after the specified 
      number of runs are performed. (BJSruns in the batchfile)
  */
  public void finalizeRunSeries()
    {};

  /** Initialize and start a single run of the algorithm. You can 
      usually just call doEA() from your framework.
  */
  public void initializeAndStartRun()
    {
      doEA();
    };

  /** Finalize the single run of the algorithm. This is called immediately
      after the initializeAndStartRun(). It can be used to reset 
      measurements, increase counters, etc.
  */
  public void finalizeRun()
    {
    };

  /** Get the run data as text. Your implementation must return
      an array of objects that each implements the interface ConvertToText from the package
      EA.recording. You can use the classes found in EA.recording or 
      implement your own classes.
      @see EA.recording.ResultSet
      @see EA.recording.Measurement
      @see EA.recording.ConvertToText
  */
  public Object[] getDataAsText()
    {
      int i;
      RKUVector resvec = new RKUVector();
      SteepestAscendIndividual best;

      if (saveallrepetitions) {
	results1 = new SequenceTable("all_repetitions");
	results1.addColumn(new SequenceTableColumn("Bestfit"));
	results1.addColumns(curproblem.getSequenceTableColumns(""));

	for (i=0; i<population.length;i++) {
	  results1.initializeRow();
	  results1.updateLastRow(0,population[i].getFitness());
	  results1.updateLastRow(1,population[i].getPos());
	}

	resvec.addElement(results1);
      }

      if (savebestrepetition) {
	results2 = new SequenceTable("best_repetition");
	results2.addColumn(new SequenceTableColumn("Bestfit"));
	results2.addColumns(curproblem.getSequenceTableColumns(""));

	best = population[PopulationMeasurements.indexOfBest(population, ismaximization)];
	results2.initializeRow();
	results2.updateLastRow(0,best.getFitness());
	results2.updateLastRow(1,best.getPos());

	resvec.addElement(results2);
      }

      return resvec.toArray();
    };

}

class SteepestAscendIndividual extends Individual implements RKUCloneable, RKUValuation, NumericalInspector
{
  int representation;


  /** Create a new SteepestAscendIndividual. 
      @param frame The framework for this individual.
      @param initialize True if you want to create a new Bit/Real-NumericalGenome.
      @param reptype The type of representation.
  */
  public SteepestAscendIndividual(NumericalFramework frame, boolean initialize, int reptype)
    {
      super(frame);
      
      representation = reptype;

      if (initialize) {
	switch(reptype) {
	case 0:
	  genome = new RealNumericalGenome((RealNumericalFramework)frame,true);
	  break;
	case 1:
	  genome = new BitNumericalGenome((BitNumericalFramework)frame,true);
	  break;
	case 2:
	  genome = new DiscreteRNumGenome((DiscreteRNumFramework)frame,true);
	  break;
	}
      }
    }

  public double getFitness()
    {
      return ((NumericalGenome)genome).getFitness();
    }

  public void localSearch()
    {
      double[] params = {0,0};

      switch(representation) {
      case 0:
	params[0] = ((RealSteepestAscendFramework)genome.framework).maxiterations;
	params[1] = ((RealSteepestAscendFramework)genome.framework).realrange;
	RNumSteepestAscend.localSearch((NumericalGenome)genome,params);
	break;
      case 1:
	System.out.println("NOT IMPLEMENTED YET!");
	System.exit(0);
	break;
      case 2:
	params[0] = ((DiscSteepestAscendFramework)genome.framework).maxiterations;
	params[1] = ((DiscSteepestAscendFramework)genome.framework).realrange;
	DRNumSteepestAscend.localSearch((NumericalGenome)genome,params);

	break;
      }
    }

  public Object clone()
    {
      SteepestAscendIndividual res;

      res = new SteepestAscendIndividual((NumericalFramework)framework, false, 0);
      res.genome = (Genome)(this.genome.clone());
      return res;
    }

  public double value()
    {
      return this.getFitness();
    }

  public double[] getPos()
    {
      return ((NumericalGenome)genome).getPos();
    }

  // Inteface-implementation: NumericalInspector
  public double[] inspectGetPos() { return getPos(); }
  public double inspectGetFitness() { return getFitness(); }
}

